Модуль:Картка
-- Модуль для реалізації шаблону -- local p = {} local HtmlBuilder2 = require('Module:HtmlBuilder2') local args = {} local origArgs local argsAliases = {} local root local function union(t1, t2) -- Повертає об'єднання значень двох таблиць у вигляді послідовності. local vals = {} for k, v in pairs(t1) do valsv = true end for k, v in pairs(t2) do valsv = true end local ret = {} for k, v in pairs(vals) do table.insert(ret, k) end return ret end local function getArgNums(prefix) -- Повертає таблицю індексів існуючих полів із заданим префіксом, -- наприклад, для префікса 'текст' і встановлених 'текст1', 'текст2' і -- 'текст5' повертає {1, 2, 5}. local nums = {} for k, v in pairs(args) do local num = tostring(k):match('^' .. prefix .. '(1-9%d*)$') if num then table.insert(nums, tonumber(num)) end end table.sort(nums) return nums end local function addRow(rowArgs) -- Додає рядок у картку (заголовок або мітку/текст). if rowArgs.header then root .tag('tr') .addClass(rowArgs.rowclass) .attr('id', rowArgs.rowid) .tag('th') .attr('colspan', 2) .attr('id', rowArgs.headerid) .addClass(rowArgs.class) .addClass(args'клас_заголовків') .css('text-align', 'center') .cssText(args'стиль_заголовків') .wikitext(rowArgs.header) elseif rowArgs.data then local row = root.tag('tr') row.addClass(rowArgs.rowclass) row.attr('id', rowArgs.rowid) if rowArgs.label then row .tag('th') .attr('scope', 'row') .attr('id', rowArgs.labelid) .css('text-align', 'left') .cssText(args'стиль_міток') .wikitext(rowArgs.label) .done() end local dataCell = row.tag('td') if not rowArgs.label then dataCell .attr('colspan', 2) .css('text-align', 'center') end dataCell .attr('id', rowArgs.dataid) .addClass(rowArgs.class) .cssText(rowArgs.datastyle) .newline() .wikitext(rowArgs.data) end end local function renderTitle() if not args'назва' then return end root .tag('caption') .addClass(args'клас_назви') .cssText(args'стиль_назви') .wikitext(args'назва') end local function renderAboveRow() if not args'угорі' then return end root .tag('tr') .tag('th') .attr('colspan', 2) .addClass(args'клас_угорі') .css('text-align', 'center') .css('font-size', '125%') .css('font-weight', 'bold') .cssText(args'стиль_угорі') .wikitext(args'угорі') end local function renderAbove2Row() if not args'угорі2' then return end root .tag('tr') .tag('th') .attr('colspan', 2) .addClass(args'клас_угорі2') .css('text-align', 'center') .css('font-style', 'oblique') .cssText(args'стиль_угорі2') .wikitext(args'угорі2') end local function renderBelowRow() if not args'внизу' then return end root .tag('tr') .tag('td') .attr('colspan', '2') .addClass(args'клас_внизу') .css('text-align', 'center') .cssText(args'стиль_внизу') .newline() .wikitext(args'внизу') end local function renderSubheaders() if args'підзаголовок' then args'підзаголовок1' = args'підзаголовок' end if args'клас_рядка_підзаголовка' then args'клас_рядка_підзаголовка1' = args'клас_рядка_підзаголовка' end local subheadernums = getArgNums('підзаголовок') for k, num in ipairs(subheadernums) do addRow({ data = args.. tostring(num), datastyle = args'стиль_підзаголовків' or args.. tostring(num), class = args'клас_підзаголовків', rowclass = args.. tostring(num) }) end end local function renderImages() if args'зображення' then args'зображення1' = args'зображення' end if args'підпис' then args'підпис1' = args'підпис' end local imagenums = getArgNums('зображення') for k, num in ipairs(imagenums) do local caption = args.. tostring(num) local data = HtmlBuilder2.create().wikitext(args.. tostring(num)) if caption then data .tag('div') .cssText(args'стиль_підпису') .wikitext(caption) end addRow({ data = tostring(data), datastyle = args'стиль_зображення', class = args'клас_зображення', rowclass = args.. tostring(num) }) end end local function renderRows() -- Об'єднує індекси заголовків і текстових рядків картки, -- і візуалізує їх у правильному порядку через addRow. local rownums = union(getArgNums('заголовок'), getArgNums('текст')) table.sort(rownums) for k, num in ipairs(rownums) do addRow({ header = args.. tostring(num), label = args.. tostring(num), data = args.. tostring(num), datastyle = args'стиль_тексту', class = args.. tostring(num), rowclass = args.. tostring(num), dataid = args.. tostring(num), labelid = args.. tostring(num), headerid = args.. tostring(num), rowid = args.. tostring(num) }) end end local function renderNavBar() if not args'ім\'я' then return end root .tag('tr') .tag('td') .attr('colspan', 2) .css('text-align', 'right') .wikitext(mw.getCurrentFrame():expandTemplate({ title = 'Tnavbar', args = { args'ім\'я', mini = 1 } })) end local function isSet(x) -- Повертає істину, якщо x вказаний і не порожній -- Увага: відрізняється від enwiki! В enwiki перевіряється на рівеність 'yes' return x and x ~= '' end local function renderItalicTitle() -- Увага: відрізняється від enwiki! В enwiki очікується yes або force, тут працює будь-яке значення if isSet(args'заголовок_курсивом') then root.wikitext(mw.getCurrentFrame():expandTemplate({title = 'Заголовок курсивом'})) end end local function renderTrackingCategories() if not isSet(args.nocat) then if #(getArgNums('текст')) 0 and mw.title.getCurrentTitle().namespace 0 then root.wikitext('Категорія:Статті з карткою без заповнених даних') end if isSet(args'встроєння') and args'назва' then root.wikitext('Категорія:Статті з вбудованою карткою і параметром назви') end end end local function _infobox() -- Задання загальної структури картки з додаванням стилів -- для карток-нащадків. if not isSet(args'встроєння') then root = HtmlBuilder2.create('table') root .addClass('infobox') .addClass(args'клас_тіла') .attr('cellspacing', 3) .css('border-spacing', '3px') if isSet(args'підкартка') then root .css('padding', '0') .css('border', 'none') .css('margin', '-3px') .css('width', 'auto') .css('min-width', '100%') .css('font-size', '100%') .css('clear', 'none') .css('float', 'none') .css('background-color', 'transparent') else root .css('width', '22em') end -- Мікророзмітка if isSet(args'мікр_тіла') then root .attr('itemscope', 'itemscope') .attr('itemtype', args'мікр_тіла') end root .cssText(args'стиль_тіла') renderTitle() renderAboveRow() renderAbove2Row() else root = HtmlBuilder2.create() root .wikitext(args'назва') end renderSubheaders() renderImages() renderRows() renderBelowRow() renderNavBar() renderItalicTitle() renderTrackingCategories() return tostring(root) end local function preprocessSingleArg(argName) -- Додає аргумент в таблицю аргументів, якщо він визначений і не порожній. -- Порожні аргументи не обробляються, як і в ParserFunctions. if origArgsargName and origArgsargName ~= '' then argsargName = origArgsargName end end local function translateArg(aliasArgName,localArgName) -- Функція додає підтримку аліасів параметрів (наприклад, іншою мовою) -- Додаєм аліас параметра в таблицю аліасів -- Для одного параметра може бути кілька аліасів -- Нумеровані параметри(текст1 і т.д.) заносяться без номера if not argsAliaseslocalArgName then argsAliaseslocalArgName = {} end table.insert(argsAliaseslocalArgName, aliasArgName) -- Пока для тестування: значення аліасів додаются в таблицю аргументів -- Нумеровані параметри не будуть працювати if origArgslocalArgName and origArgslocalArgName ~= '' then -- параметр вже задан на локальній мові else -- якщо аліас заданий і не пустий if origArgsaliasArgName and origArgsaliasArgName ~= '' then origArgslocalArgName = origArgsaliasArgName end end end local function preprocessArgs(prefixTable, step) -- Зберігає параметри з заданими префіксами в таблицю args, послідовно обходячи -- аргументи в потрібному порядку і з потрібним кроком. Завдяки цьому виноски та ін. з'являються -- в правильному порядку. prefixTable — масив таблиць, кожна з яких може містити -- два поля: a "prefix" string and a "depend" table. The function always parses -- Ця функція завжди обробляє параметри з префіксом, але залежні параметри -- обробляються, тільки якщо параметр з префіксом заданий і не порожній. if type(prefixTable) ~= 'table' then error("В якості таблиці префіксів повинна використовуватися таблиця", 2) end if type(step) ~= 'number' then error("Неприпустимий тип параметра кроку", 2) end -- Перевірка правильності даних та обробка параметрів без суфіксів. for i,v in ipairs(prefixTable) do if type(v) ~= 'table' or type(v.prefix) ~= "string" or (v.depend and type(v.depend) ~= 'table') then error('Неприпустима таблиця префіксів preprocessArgs', 2) end preprocessSingleArg(v.prefix) -- Залежні параметри обробляються, тільки якщо параметр з префіксом заданий і не порожній. if argsv.prefix and v.depend then for j, dependValue in ipairs(v.depend) do if type(dependValue) ~= 'string' then error('Неприпустимий тип залежного параметра в таблиці preprocessArgs') end preprocessSingleArg(dependValue) end end end -- Обхід нумерованих аргументів. local a = 1 -- Змінна-лічильник. local moreArgumentsExist = true while moreArgumentsExist true do moreArgumentsExist = false for i = a, a + step - 1 do for j,v in ipairs(prefixTable) do local prefixArgName = v.prefix .. tostring(i) if origArgsprefixArgName then moreArgumentsExist = true -- Шукати аргументи далі, якщо був хоча б один (в т. ч. порожній) preprocessSingleArg(prefixArgName) end -- Обробляємо залежні аргументи, якщо визначена таблиця залежностей, -- а також вказаний не порожній аргумент з префіксом, або обробляється -- "префікс1" і "префікс" заданий (наприклад, "зображення1" являється синонімом для "зображення"). if v.depend and (argsprefixArgName or (i 1 and argsv.prefix)) then for j,dependValue in ipairs(v.depend) do local dependArgName = dependValue .. tostring(i) preprocessSingleArg(dependArgName) end end end end a = a + step end end function p.infobox(frame) -- При запуску через #invoke аргументи передаються через стандартну систему. -- При тестуванні також можна передавати таблицю аргументів через frame. if frame mw.getCurrentFrame() then origArgs = frame:getParent().args else origArgs = frame end -- Підтримка параметрів з англовікі translateArg('child','встроєння') translateArg('bodyclass','клас_тіла') translateArg('subbox','підкартка') translateArg('bodystyle','стиль_тіла') translateArg('title','назва') translateArg('titleclass','клас_назви') translateArg('titlestyle','стиль_назви') translateArg('above','угорі') translateArg('aboveclass','клас_угорі') translateArg('abovestyle','стиль_угорі') translateArg('subheader','підзаголовок') translateArg('subheaderstyle','стиль_підзаголовка') translateArg('subheaderrowclass','клас_підзаголовка') translateArg('subheaderstyle','стиль_підзаголовків') translateArg('subheaderclass','клас_підзаголовків') translateArg('image','зображення') translateArg('caption','підпис') translateArg('imagerowclass','клас_рядка_зображення') translateArg('captionstyle','стиль_підпису') translateArg('imagestyle','стиль_зображення') translateArg('imageclass','клас_зображення') translateArg('header','заголовок') translateArg('data','текст') translateArg('label','мітка') translateArg('rowclass','клас_рядка') translateArg('class','клас') translateArg('dataid','id_тексту') translateArg('labelid','id_мітки') translateArg('headerid','id_заголовка') translateArg('rowid','id_рядка') translateArg('headerclass','клас_заголовків') translateArg('headerstyle','стиль_заголовків') translateArg('labelstyle','стиль_міток') translateArg('datastyle','стиль_тексту') translateArg('below','внизу') translateArg('belowclass','клас_внизу') translateArg('belowstyle','стиль_внизу') translateArg('name','ім\'я') --translateArg('italic title','заголовок_курсивом') --translateArg(,) -- Параметри обробляються в напрямку читання картки, щоб -- виноски та ін. відображалися в потрібних місцях. Параметри, що залежать -- від інших параметрів, обробляються тільки за наявності інших параметрів, -- щоб у списку виносок не виникали небажані виноски. preprocessSingleArg('встроєння') preprocessSingleArg('клас_тіла') preprocessSingleArg('підкартка') preprocessSingleArg('стиль_тіла') preprocessSingleArg('назва') preprocessSingleArg('клас_назви') preprocessSingleArg('стиль_назви') preprocessSingleArg('угорі') preprocessSingleArg('клас_угорі') preprocessSingleArg('стиль_угорі') preprocessSingleArg('угорі2') preprocessSingleArg('клас_угорі2') preprocessSingleArg('стиль_угорі2') preprocessArgs({ {prefix = 'підзаголовок', depend = {'стиль_підзаголовка', 'клас_підзаголовка'}} }, 10) preprocessSingleArg('стиль_підзаголовків') preprocessSingleArg('клас_підзаголовків') preprocessArgs({ {prefix = 'зображення', depend = {'підпис', 'клас_рядка_зображення'}} }, 10) preprocessSingleArg('стиль_підпису') preprocessSingleArg('стиль_зображення') preprocessSingleArg('клас_зображення') preprocessArgs({ {prefix = 'заголовок'}, {prefix = 'текст', depend = {'мітка'}}, {prefix = 'клас_рядка'}, {prefix = 'клас'}, {prefix = 'id_тексту'}, {prefix = 'id_мітки'}, {prefix = 'id_заголовка'}, {prefix = 'id_рядка'} }, 50) preprocessSingleArg('клас_заголовків') preprocessSingleArg('стиль_заголовків') preprocessSingleArg('стиль_міток') preprocessSingleArg('стиль_тексту') preprocessSingleArg('внизу') preprocessSingleArg('клас_внизу') preprocessSingleArg('стиль_внизу') preprocessSingleArg('ім\'я') preprocessSingleArg('заголовок_курсивом') preprocessSingleArg('nocat') return _infobox() end return p